home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / byte0387.arc / BIXMODEM.INC < prev    next >
Text File  |  1980-01-01  |  10KB  |  416 lines

  1. again
  2. ==========================
  3. pc.bix/source.code #28, from barryn, 9661 chars, Thu Jun 26 19:48:15 1986
  4. --------------------------
  5. TITLE: BIXMODEM.INC
  6.  
  7. {                                                             }
  8. {                                                             }
  9. { BIXMODEM.INC  Ymodem procedures for use with BIX.PAS        }
  10. {                                                             }
  11. {                                                             }
  12. {      Program and all Supporting Materials Copyright         }
  13. {      (c) 1985 Barry R. Nance                                }
  14. {               17 Pease Street                               }
  15. {               Wilbraham, Massachusetts 01095                }
  16. {               (413) 596-4031                                }
  17. {                                                             }
  18. {                                                             }
  19.  
  20.  
  21. Var  CRCWork : Integer;
  22.      CRC     : Integer;
  23.  
  24. Function PartialCrc (OldCRC:Integer; C:Char) : Integer;
  25.          {done in 80x8x assembler for speed}
  26. Begin
  27.   CRCWork := OldCRC;
  28.  
  29.   INLINE( $8A / $46 / $04 /        (* Mov     Al,[Bp+4]   *)
  30.           $8B / $1E / CRCWork /    (* Mov     Bx,CRCWork  *)
  31.           $B9 / $08 / $00 /        (* Mov     Cx,8        *)
  32. {Oloop:}  $D0 / $E0 /              (* Shl     Al,1        *)
  33.           $D1 / $D3 /              (* Rcl     Bx,1        *)
  34.           $73 / $04 /              (* Jnc     Iloop       *)
  35.           $81 / $F3 / $21 / $10 /  (* Xor     Bx,$1021    *)
  36. {Iloop:}  $E2 / $F4 /              (* Loop    Oloop       *)
  37.           $89 / $1E / CRCWork )    (* Mov     CRCWork,BX  *);
  38.  
  39.   PartialCRC := CRCWork;
  40.   End;
  41.  
  42.  
  43.  
  44. Procedure ReceiveXMODEM (XName : Str20);
  45. Const
  46.     SOH   = #$01;
  47.     STX   = #$02;
  48.     EOT   = #$04;
  49.     ACK   = #$06;
  50.     NAK   = #$15;
  51.     C_Ch  = 'C';
  52.  
  53.  
  54. Type
  55.     YrecDef     = Array [1..1024] of Char;
  56.     XrecDef     = Array [1..128]  of Char;
  57.  
  58. Var
  59.     Xrec        : XrecDef;
  60.     Yrec        : YrecDef;
  61.     XFile       : File of XrecDef;
  62.  
  63.     XSub        : Integer;
  64.     ErrCnt      : Integer;
  65.     BlockError  : Boolean;
  66.     CurrBlock   : Integer;
  67.     EOTdetected : Boolean;
  68.     BlockLength : Integer;
  69.     Duplicate   : Boolean;
  70.     GetOutFlag  : Boolean;
  71.     FirstNAK    : Boolean;
  72.  
  73.  
  74.  
  75.       Function Abort : Boolean;
  76.       Begin
  77.         Abort := False;
  78.  
  79.         If ErrCnt > 10 then
  80.            Begin 
  81.              HighVideo;
  82.              Write (^G);
  83.              Write (
  84.      'Ten errors have occurred on this block.  Continue (Y/N)? ');
  85.              LowVideo;
  86.              Repeat Read(kbd, Key) Until UpCase(Key) in ['N', 'Y'];
  87.              Writeln (Key);
  88.              If UpCase(Key) = 'N' then
  89.                 Begin
  90.                   Abort      := True;
  91.                   GetOutFlag := True;
  92.                   End
  93.              Else
  94.                 ErrCnt := 0;
  95.              End;
  96.  
  97.         End;
  98.  
  99.  
  100.  
  101.  
  102.       Procedure SendNAK;
  103.       Begin
  104.         PurgeBuffer;
  105.  
  106.         If Duplicate then Exit;
  107.  
  108.         SendChar(NAK);
  109.         Writeln ('Requesting re-transmission of block # ', CurrBlock);
  110.         ErrCnt     := Succ(ErrCnt);
  111.         BlockError := True;
  112.         End;
  113.  
  114.  
  115.  
  116.  
  117.       Procedure SendACK;
  118.       Begin 
  119.         SendChar(ACK);
  120.         ErrCnt := 0;
  121.         End;
  122.  
  123.  
  124.  
  125.  
  126.       Procedure ReceiveSOH;
  127.       Begin
  128.         ReceiveChar (10, Ch, TimedOut);
  129.  
  130.         If Ch = EOT then
  131.            Begin
  132.              EOTdetected := True;
  133.              SendACK;
  134.              Exit;
  135.              End;
  136.  
  137.         If Ch = C_Ch then
  138.            If CurrBlock = 1 then
  139.               ReceiveChar (10, Ch, TimedOut);
  140.  
  141.         If TimedOut then
  142.            If CurrBlock = 1 then
  143.               If FirstNAK then
  144.                  Begin
  145.                    FirstNAK := False;
  146.                    SendChar (NAK);
  147.                    ReceiveChar (10, Ch, TimedOut);
  148.                    End;
  149.  
  150.         If (TimedOut)
  151.                or
  152.            ((Ch <> SOH) And (Ch <> STX))  then
  153.            Begin
  154.              If TimedOut then
  155.                 Writeln ('Timed out on SOH/STX.')
  156.              Else
  157.                 Writeln ('1st char not SOH/STX.');
  158.              SendNAK;
  159.              End
  160.         Else
  161.             If Ch = STX then
  162.                BlockLength := 1024
  163.             Else
  164.                BlockLength := 128;
  165.         End;
  166.  
  167.  
  168.  
  169.  
  170.       Procedure ReceiveBlockNum;
  171.       Var    Blk     : Byte;
  172.              PrevBlk : Byte;
  173.              FirstCh : Char;
  174.       Begin
  175.         If BlockError then Exit;
  176.  
  177.         Duplicate := False;
  178.         Blk       := CurrBlock Mod 256;
  179.         PrevBlk   := (CurrBlock - 1) Mod 256;
  180.         ReceiveChar (1, Ch, TimedOut);
  181.         FirstCh := Ch;
  182.  
  183.         If (TimedOut) or (Ord(Ch) <> Blk)  then
  184.            If Ord(Ch) <> PrevBlk then
  185.               Begin 
  186.                 SendNAK;
  187.                 If TimedOut then
  188.                    Writeln ('Timed out on block number.')
  189.                 Else
  190.                    Writeln ('Block number error (calcd = ', Blk, ').');
  191.                 Exit;
  192.                 End;
  193.  
  194.         ReceiveChar (1, Ch, TimedOut);
  195.         Blk     := 255 - Blk;
  196.         PrevBlk := 255 - PrevBlk;
  197.  
  198.         If (TimedOut) or (Ord(Ch) <> Blk) then
  199.            If Ord(Ch) <> PrevBlk then
  200.               Begin 
  201.                 SendNAK;
  202.                 If TimedOut then
  203.                    Writeln ('Timed out on complement.')
  204.                 Else
  205.                    Writeln ('Complement error (calcd = ', Blk, ').');
  206.                 Exit;
  207.                 End;
  208.  
  209.         If Ord(Ch) = PrevBlk then
  210.            If Ord(FirstCh) = CurrBlock Mod 256 then
  211.               Duplicate := True;
  212.  
  213.         End;
  214.  
  215.  
  216.  
  217.  
  218.       Procedure ReceiveDataBlock;
  219.       Begin
  220.         If BlockError then Exit;
  221.         OverrunError := False;
  222.  
  223.  
  224.         Repeat
  225.           XSub := Succ(XSub);
  226.           ReceiveChar (1, Ch, TimedOut);
  227.  
  228.           If Not TimedOut then
  229.              Begin
  230.                Yrec [XSub] := Ch;
  231.                If BlockLength = 1024 then
  232.                   CRC := PartialCRC (CRC, Ch);
  233.                End;
  234.  
  235.           Until (TimedOut) or (XSub = BlockLength) or (OverrunError);
  236.  
  237.  
  238.         If (TimedOut) or (OverrunError) then
  239.            Begin
  240.              SendNAK;
  241.              If TimedOut then
  242.                 Writeln ('Timed out waiting for data.')
  243.              Else
  244.                 Writeln ('Overrun error occurred.');
  245.              OverrunError := False;
  246.              End;
  247.         End;
  248.  
  249.  
  250.  
  251.       Procedure ReceiveCheckSum;
  252.       Var    ChkSum : Byte;
  253.       Begin
  254.         If BlockError then Exit;
  255.         ReceiveChar (1, Ch, TimedOut);
  256.         ChkSum := 0;
  257.         For XSub := 1 to 128 Do
  258.             ChkSum := ChkSum + Ord(Yrec[XSub]);
  259.         If (TimedOut) or (ChkSum <> Ord(Ch)) then
  260.            Begin 
  261.              SendNak;
  262.              If TimedOut then
  263.                 Writeln ('Timed out on checksum.')
  264.              Else
  265.                 Writeln (
  266.                 'Checksum error (is ', Ord(Ch), '; should be ', ChkSum, ').');
  267.              End;
  268.         End;
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.       Procedure ReceiveCRC;
  276.       Var
  277.         CRCin  : Integer;
  278.  
  279.       Begin
  280.         If BlockError then Exit;
  281.  
  282.         ReceiveChar (1, Ch, TimedOut);
  283.  
  284.         If Not TimedOut then
  285.            Begin
  286.              CRC   := PartialCRC (CRC, Ch);
  287.              CRCin := ord(Ch) * 256;
  288.              ReceiveChar (1, Ch, TimedOut);
  289.              If Not TimedOut then
  290.                 Begin
  291.                   CRC   := PartialCRC (CRC, Ch);
  292.                   CRCin := CRCin + ord(Ch);
  293.                   End;
  294.              End;
  295.  
  296.         If (TimedOut) or (CRC <> 0) then
  297.            Begin
  298.              SendNAK;
  299.              If TimedOut then
  300.                 Writeln ('Timed out on CRC.')
  301.              Else
  302.                 Writeln (
  303.                 'CRC error (is ', CRCin, '; should be ', CRC, ').');
  304.              End;
  305.         End;
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312. Procedure GetXMODEMBlock;
  313. Begin
  314.   If Keypressed then
  315.      Begin
  316.        GetKey (Key, Extended);
  317.        If Key = Chr(27) then
  318.           Begin
  319.             GetOutFlag := True;
  320.             Exit;
  321.             End;
  322.        End;
  323.  
  324.   BlockError := False;
  325.   ReceiveSOH;
  326.  
  327.   If EOTdetected then Exit;
  328.  
  329.   ReceiveBlockNum;
  330.  
  331.   XSub := 0; CRC := 0;
  332.   ReceiveDataBlock;
  333.  
  334.   If BlockLength = 1024 then
  335.      ReceiveCRC
  336.   Else
  337.      ReceiveCheckSum;
  338.  
  339.   If Not BlockError then
  340.      Begin                 
  341.        SendACK;
  342.        If Not Duplicate then
  343.           Begin
  344.             Writeln ('Block # ', CurrBlock, ' received.');
  345.             If BlockLength = 128 then
  346.                Begin
  347.                  Move  (Yrec[1], Xrec[1], 128);
  348.                  Write (XFile, Xrec);
  349.                  End
  350.             Else
  351.                Begin
  352.                  For XSub := 1 to 8 Do
  353.                      Begin
  354.                        Move  (Yrec[((XSub - 1) * 128) + 1], Xrec[1], 128);
  355.                        Write (XFile, Xrec);
  356.                        End;
  357.                  End;
  358.             CurrBlock := Succ(CurrBlock);
  359.             End;
  360.        End;
  361.   End;
  362.  
  363.  
  364.  
  365.  
  366.  
  367. Begin                        {of ReceiveXMODEM}
  368.   If XName = '' then Exit;
  369.  
  370.   Assign  (XFile, XName);
  371.   Rewrite (XFile);
  372.  
  373.   Writeln ('File ', XName, ' is being received.');
  374.   Writeln;
  375.  
  376.   UpdateUART (8, 'N', 1);
  377.   PurgeBuffer;
  378.   SendChar(C_Ch);
  379.  
  380.   FirstNAK      := True;
  381.   OverrunError  := False;
  382.   DoingXMODEM   := True;
  383.   XSub          := 0;
  384.   ErrCnt        := 0;
  385.   CurrBlock     := 1;
  386.   BlockError    := False;
  387.   EOTdetected   := False;
  388.   Duplicate     := False;
  389.   GetOutFlag    := False;
  390.  
  391.   Repeat
  392.     GetXMODEMBlock;
  393.     Until (Abort) or (EOTdetected) or (GetOutFlag);
  394.  
  395.   If GetOutFlag then
  396.      Begin
  397.        Close   (XFile);
  398.        Erase   (XFile);
  399.        Writeln ('ERROR--reception of ', XName, ' cancelled.  File erased.');
  400.        End
  401.   Else
  402.      Begin
  403.        Close   (XFile);
  404.        Writeln;
  405.        Writeln (XName, ' successfully received.');
  406.        End;
  407.  
  408.   DoingXMODEM:= False;
  409.   UpdateUART (7, 'E', 1);
  410.  
  411.   End;
  412.  
  413.  
  414.  
  415.  
  416. Read: